package com.a918.consensus;

import java.sql.Array;
import java.sql.Timestamp;
import java.util.*;

public class ForPlatForm {
    private static final int RANDOM_SEED = 12345;
    private static final double TIME_LIMIT = 4;
    private static final int SAMPLES = 1000;
    private static final double reward = 0.5;   //出块奖励
    private static final double beta = 0.8;           //普通节点奖励占比
    private static final int round=60;
    private static final int correctNodeCnt=90; //正常节点
    private static final int failNodeCnt=10;  //恶意节点
    private static final int token=20;
    private static final double credit=0.5;
    private static final int delegetNum=21;
    private static final double initialTimeout = 0.1;


    public static void main(String[] args) {
        // **运行示例**


        // 运行与可视化分析
        // 1 (1)
        //List<Integer> runRounds1 = Arrays.asList(10,20,30,40,50,60);
        //Map<Integer,Double> result11 = GetVerifyTimeDelayDPoSPT(initialTimeout,correctNodeCnt,failNodeCnt,token,credit,round,delegetNum,TIME_LIMIT,reward,beta,runRounds1);
        //System.out.println(result11);// {50=0.3628486907032223, 20=0.3636478910853339, 40=0.36333839492499476, 10=0.3654553291495253, 60=0.36328718834411056, 30=0.3631583876669341}

        // 1 (2)

        // 2 (1)

        // 2 (2)

        // 3 (1)
        List<Integer> rounds = Arrays.asList(2,3,4,5,6,7,8,9,10);
        Map<Integer,Double> result31 = GetFailNodeRateDPoSPT(initialTimeout,correctNodeCnt,failNodeCnt,token,credit,rounds,delegetNum,TIME_LIMIT,reward,beta,100);
        System.out.println(result31);//{2=0.0747619047619047, 3=0.05492063492063488, 4=0.04476190476190472, 5=0.045238095238095195, 6=0.031825396825396784, 7=0.029999999999999985, 8=0.029285714285714262, 9=0.02375661375661375, 10=0.020857142857142838}
        // 3 (2)
        //Map<Integer,Double> result32 = GetFailNodeRateDPoS(initialTimeout,correctNodeCnt,failNodeCnt,token,credit,rounds,delegetNum,TIME_LIMIT,reward,beta,100);
        //System.out.println(result32);//{2=0.08928571428571422, 3=0.09682539682539679, 4=0.09999999999999995, 5=0.1002857142857142, 6=0.09976190476190469, 7=0.09292517006802715, 8=0.0950595238095238, 9=0.09793650793650788, 10=0.09852380952380944}
        // 4 (1)
        //List<Integer> rounds = Arrays.asList(1,2,3,4,5,6);
        //Map<Integer,Double> result41 = GetGiniIndexDPoSPT(initialTimeout,correctNodeCnt,failNodeCnt,token,credit,rounds,delegetNum,TIME_LIMIT,reward,beta,100);
        //System.out.println(result41);//{1=0.002918798428324597, 2=0.005159826480120235, 3=0.007044080562376068, 4=0.008999459019784287, 5=0.010781530412601159, 6=0.01254165252783137}
        // 4 (2)
        //Map<Integer,Double> result42 = GetGiniIndexDPoS(initialTimeout,correctNodeCnt,failNodeCnt,token,credit,rounds,delegetNum,TIME_LIMIT,reward,beta,100);
        //System.out.println(result42);// {1=0.0038074259535822857, 2=0.0076335205678219956, 3=0.011276127794734943, 4=0.015058200158063377, 5=0.01854885561769775, 6=0.022258254079110237}

    }

    // 1. 验证时延分析
    /*
        - 不同选举轮次下区块验证时延 *6
        - 不同时间间隔区块验证时延
        - 不同共识算法区块验证时延对比 DPoS DPoSPT
     */
    // (1) 不同时间间隔区块验证时延:DPoSPT
    public static Map<Integer,Double> GetVerifyTimeDelayDPoSPT(double initialTimeout, int correctNodeCount, int failedNodeCout, double token, double credit, int round, int delegateNum, double TIME_LIMIT, double reward, double beta, // 这一行参数是runDPOSPT的输入参数
                                                         List<Integer> runRounds){
        Map<Integer,Double> result = new HashMap<>();
        /*
            x轴： 运行轮次，例如 runRounds = [10,20,30,40,50,60]
            y轴： 平均确认时延数据，例如 366.671412973308, 363.0239429408772, 363.909362302117, 363.57443426451436, 363.6988453176527,362.5423496443487
         */

        for (Integer runRound : runRounds) {
            double dposptAvgTime = ConsensusAlgorithmOperation.getAvgTime(runRound,initialTimeout,correctNodeCount,failedNodeCout,token,credit,round,delegateNum,TIME_LIMIT,reward,beta);
            result.put(runRound,dposptAvgTime);
        }

        return result;
    }


    // (2) 不同时间间隔区块验证时延:DPoS
    public static Map<Integer,Double> GetVerifyTimeDelayDPoS(double initialTimeout, int correctNodeCount, int failedNodeCout, double token, double credit, int round, int delegateNum, double TIME_LIMIT, double reward, double beta, // 这一行参数是runDPOSPT的输入参数
                                                               List<Integer> runRounds){
        Map<Integer,Double> result = new HashMap<>();
        /*
            x轴： 运行轮次，例如 runRounds = [10,20,30,40,50,60]
            y轴： 平均确认时延数据，例如 366.671412973308, 363.0239429408772, 363.909362302117, 363.57443426451436, 363.6988453176527,362.5423496443487
         */
        // 没有看到runDPoS有统计确认时延的数据，我猜宙哥画图那里的DPoS确认时延[660, 658, 654, 673, 679,671]是假数据

        return result;
    }

    // 2. 吞吐量分析
    /*
        - 不同共识次数下有效区块数量统计图 *6 DPoS DPoSPT
        - 不同共识次数下平均有效区块数量 DPoS DPoSPT
     */
    // 没找到有效区块数量统计的代码


    // 3. 恶意节点占比分析
    /*
        - 恶意节点占比对图 DPoS DPoSPT
     */
    public static Map<Integer,Double> GetFailNodeRateDPoSPT(double initialTimeout, int correctNodeCount, int failedNodeCout, double token, double credit, List<Integer> rounds, int delegateNum, double TIME_LIMIT, double reward, double beta, // 这一行参数是runDPOSPT的输入参数
                                                               Integer runRound){
        Map<Integer,Double> result = new HashMap<>();
        /*
            x轴： 选举轮数，例如 rounds = [2,4,6,8,10]
            y轴： 平均恶意节点占比率
         */

        for (Integer round : rounds) {
            double dposptFailRate = ConsensusAlgorithmOperation.getAvgFailRate(runRound,"DPoSPT",initialTimeout,correctNodeCount,failedNodeCout,token,credit,round,delegateNum,TIME_LIMIT,reward,beta);
            result.put(round,dposptFailRate);
        }

        return result;
    }

    public static Map<Integer,Double> GetFailNodeRateDPoS(double initialTimeout, int correctNodeCount, int failedNodeCout, double token, double credit, List<Integer> rounds, int delegateNum, double TIME_LIMIT, double reward, double beta, // 这一行参数是runDPOSPT的输入参数
                                                          Integer runRound){
        Map<Integer,Double> result = new HashMap<>();
        /*
            x轴： 选举轮数，例如 rounds = [2,4,6,8,10]
            y轴： 平均恶意节点占比率
         */

        for (Integer round : rounds) {
            double dposFailRate = ConsensusAlgorithmOperation.getAvgFailRate(runRound,"DPoS",initialTimeout,correctNodeCount,failedNodeCout,token,credit,round,delegateNum,TIME_LIMIT,reward,beta);
            result.put(round,dposFailRate);
        }

        return result;
    }



    // 4. 去中心化分析
    /*
        - 平均基尼系数对比图 DPoS DPoSPT
     */

    public static Map<Integer,Double> GetGiniIndexDPoSPT(double initialTimeout, int correctNodeCount, int failedNodeCout, double token, double credit, List<Integer> rounds, int delegateNum, double TIME_LIMIT, double reward, double beta, // 这一行参数是runDPOSPT的输入参数
                                                            Integer runRound){
        Map<Integer,Double> result = new HashMap<>();
        /*
            x轴： 选举轮数，例如 rounds = [2,4,6,8,10]
            y轴： 平均基尼系数
         */

        for (Integer round : rounds) {
            double dposptGiniIndex = ConsensusAlgorithmOperation.getAvgGini(runRound,"DPoSPT",initialTimeout,correctNodeCount,failedNodeCout,token,credit,round,delegateNum,TIME_LIMIT,reward,beta);
            result.put(round,dposptGiniIndex);
        }

        return result;
    }

    public static Map<Integer,Double> GetGiniIndexDPoS(double initialTimeout, int correctNodeCount, int failedNodeCout, double token, double credit, List<Integer> rounds, int delegateNum, double TIME_LIMIT, double reward, double beta, // 这一行参数是runDPOSPT的输入参数
                                                        Integer runRound){
        Map<Integer,Double> result = new HashMap<>();
        /*
            x轴： 选举轮数，例如 rounds = [2,4,6,8,10]
            y轴： 平均基尼系数
         */

        for (Integer round : rounds) {
            double dposGiniIndex = ConsensusAlgorithmOperation.getAvgGini(runRound,"DPoS",initialTimeout,correctNodeCount,failedNodeCout,token,credit,round,delegateNum,TIME_LIMIT, reward, beta);
            result.put(round,dposGiniIndex);
        }

        return result;
    }

}
